package com.example.ble_demo

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
import android.bluetooth.BluetoothGattServer
import android.bluetooth.BluetoothGattServerCallback
import android.bluetooth.BluetoothGattService
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothProfile
import android.bluetooth.BluetoothServerSocket
import android.bluetooth.BluetoothSocket
import android.bluetooth.le.AdvertiseCallback
import android.bluetooth.le.AdvertiseData
import android.bluetooth.le.AdvertiseSettings
import android.bluetooth.le.BluetoothLeAdvertiser
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.ParcelUuid
import android.util.Log
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import com.example.ble_demo.bean.DeviceInfoBean
import com.example.ble_demo.databinding.ActivityMainBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.IOException
import java.lang.reflect.InvocationTargetException
import java.util.UUID


class MainActivity : AppCompatActivity() {
    private val TAG: String = "MainActivity"
    val _sTag = "MainActivity"
    lateinit var viewModel: DeviceListViewModel
    private var bluetoothManager: BluetoothManager? = null
    private var bluetoothAdapter: BluetoothAdapter? = null
    lateinit var binding: ActivityMainBinding
    var advertiser: BluetoothLeAdvertiser? = bluetoothAdapter?.bluetoothLeAdvertiser
    var mAdvertiseCallback: AdvertiseCallback? = null
    var isEnableBle = false
    var mBluetoothServerSocket: BluetoothServerSocket? = null
    val mServiceUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
    val mGATTServiceUUID = UUID.fromString("00001102-0000-1000-8000-00805F9B34FB")
    val mGATTCharacteristicUUID = UUID.fromString("00001103-0000-1000-8000-00805F9B34FB")
    val mGATTDescriptorUUID = UUID.fromString("00001104-0000-1000-8000-00805F9B34FB")
    var bluetoothScanner: BluetoothLeScanner? = null
    var isScanning = false
    var mBluetoothGattServer: BluetoothGattServer? = null

    @RequiresApi(Build.VERSION_CODES.S)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProvider(this)[DeviceListViewModel::class.java]
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        supportFragmentManager.beginTransaction().add(R.id.frameLayout, DeviceListFragment()).commit()
        //1. 获取蓝牙适配器
        bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        bluetoothAdapter = bluetoothManager?.adapter
        registerBlueToothReceiver()
        //2. 判断是否支持蓝牙
        if (bluetoothAdapter == null) {
            //  设备不支持蓝牙
            Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show()
        } else {
            //3.判断是否支持BLE
            val hasBLE = packageManager!!.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
            if (!hasBLE) {
                Toast.makeText(this, "不支持BLE", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this, "支持BLE", Toast.LENGTH_SHORT).show()
                //4.判断蓝牙是否开启
                if (!bluetoothAdapter!!.isEnabled) {
                    Toast.makeText(this, "蓝牙未开启", Toast.LENGTH_SHORT).show()
                    //5.蓝牙开启
                    if (checkPermission(Manifest.permission.BLUETOOTH_CONNECT) || ContextCompat.checkSelfPermission(
                            this, Manifest.permission.BLUETOOTH_ADVERTISE
                        ) != PackageManager.PERMISSION_GRANTED
                    ) {
                        requestPermission()
                    } else {
                        enableBluetooth()
                    }

                } else {
                    Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show()
                    isEnableBle = true
                    requestPermission()
                }
            }

        }

        val (mAdvertiseCallback: AdvertiseCallback, advertiser: BluetoothLeAdvertiser?) = advertiseCallbackBluetoothLeAdvertiserPair()
        binding.btStartAdvertise.setOnClickListener {
            if (bluetoothAdapter?.isMultipleAdvertisementSupported != true) {
                Log.e(_sTag, "Device doesn't support multiple advertisements!")
                return@setOnClickListener
            }
            if (advertiser == null) {
                Log.e(_sTag, "Unable to advertise on this device!")
                return@setOnClickListener
            }
            startAdvertise(advertiser, mAdvertiseCallback)
        }

        binding.btStartScan.setOnClickListener {
//            6.开启扫描
//            startScan()
            startScan2()
        }
        binding.btStopAdvertise.setOnClickListener {
            Log.d(_sTag, "StopAdvertise  advertiser：$advertiser  ---  mAdvertiseCallback：$mAdvertiseCallback")
            advertiser?.stopAdvertising(mAdvertiseCallback)
        }
        binding.startServiceBtn.setOnClickListener {
//            createBluetoothServer()
            createGattServer()
        }
    }

    @RequiresApi(Build.VERSION_CODES.S)
    private fun requestPermission() {
        val isGranted =
            checkPermission(Manifest.permission.BLUETOOTH_CONNECT) || checkPermission(Manifest.permission.BLUETOOTH_ADVERTISE) || checkPermission(
                Manifest.permission.BLUETOOTH_SCAN
            ) || checkPermission(Manifest.permission.BLUETOOTH_ADMIN) || checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)
        if (isGranted) {
            val permissionLauncher =
                registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { map ->
                    map.forEach {
                        if (it.key == Manifest.permission.BLUETOOTH_ADVERTISE && it.value) {
                            Toast.makeText(this, "BLUETOOTH_ADVERTISE权限申请-成功", Toast.LENGTH_SHORT).show()
                        } else {
                            Toast.makeText(this, "BLUETOOTH_ADVERTISE权限申请-失败", Toast.LENGTH_SHORT).show()
                            finish()
                        }

                        if (it.key == Manifest.permission.BLUETOOTH_CONNECT && it.value) {
                            Toast.makeText(this, "BLUETOOTH_CONNECT权限申请-成功", Toast.LENGTH_SHORT).show()
                            if (!isEnableBle) enableBluetooth()
                        } else {
                            Toast.makeText(this, "BLUETOOTH_CONNECT权限申请-失败", Toast.LENGTH_SHORT).show()
                            finish()
                        }
                        if (it.key == Manifest.permission.BLUETOOTH_SCAN && it.value) {
                            Toast.makeText(this, "BLUETOOTH_SCAN权限申请-成功", Toast.LENGTH_SHORT).show()
                            if (!isEnableBle) enableBluetooth()
                        } else {
                            Toast.makeText(this, "BLUETOOTH_SCAN权限申请-失败", Toast.LENGTH_SHORT).show()
                            finish()
                        }
                    }
                }
            permissionLauncher.launch(
                arrayOf(
                    Manifest.permission.BLUETOOTH_CONNECT,
                    Manifest.permission.BLUETOOTH_ADVERTISE,
                    Manifest.permission.BLUETOOTH_SCAN,
                    Manifest.permission.BLUETOOTH_ADMIN,
                    Manifest.permission.ACCESS_FINE_LOCATION
                )
            )
        }
    }

    private fun startAdvertise(
        advertiser: BluetoothLeAdvertiser, mAdvertiseCallback: AdvertiseCallback
    ) {
        val settings = AdvertiseSettings.Builder().setConnectable(true)
            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
            .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM).setConnectable(true).setTimeout(0).build()
        val data = "Hello World".toByteArray()
        val advertiseData = AdvertiseData.Builder().setIncludeDeviceName(true) //  包含设备名称
//            .addServiceUuid(ParcelUuid.fromString(mServiceUUID.toString()))
            .addServiceUuid(ParcelUuid.fromString(mGATTServiceUUID.toString()))
//            //                    .addManufacturerData(0x1234, byteArrayOf(0x01, 0x02, 0x03, 0x04, 0x05, 0x06))
//            .addServiceData(ParcelUuid.fromString("0000180d-0003-1000-8000-00805f9b34fa"), data)
            .build()//  添加服务UUID
        if (ContextCompat.checkSelfPermission(
                this, Manifest.permission.BLUETOOTH_ADVERTISE
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            finish()
        } else {
            advertiser.startAdvertising(settings, advertiseData, mAdvertiseCallback)
        }
    }

    private fun advertiseCallbackBluetoothLeAdvertiserPair(): Pair<AdvertiseCallback, BluetoothLeAdvertiser?> {
        val mAdvertiseCallback: AdvertiseCallback = object : AdvertiseCallback() {
            override fun onStartSuccess(settingsInEffect: AdvertiseSettings) {
                Log.d(_sTag, "Advertisement successful")
                Toast.makeText(this@MainActivity, "Advertisement successful", Toast.LENGTH_LONG).show()
            }

            override fun onStartFailure(errorCode: Int) {
                Log.e(_sTag, "Advertisement failed error code: $errorCode")
                Toast.makeText(this@MainActivity, "Advertisement failed error code: $errorCode", Toast.LENGTH_LONG)
                    .show()
            }
        }

        val advertiser: BluetoothLeAdvertiser? = bluetoothAdapter?.bluetoothLeAdvertiser
        return Pair(mAdvertiseCallback, advertiser)
    }

    private fun enableBluetooth() {
        register(
            "android.bluetooth.adapter.action.STATE_CHANGED", ActivityResultContracts.StartActivityForResult()
        ) {
            if (it.resultCode == RESULT_OK) {
                //蓝牙开启成功
                Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show()
            } else {
                //蓝牙开启失败
                Toast.makeText(this, "蓝牙开启失败", Toast.LENGTH_SHORT).show()
            }
        }.launch(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))

//        val activityLauncher =
//            registerForActivityResult(ActivityResultContracts.StartActivityForResult())
//        activityLauncher.launch(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
    }

    @RequiresApi(Build.VERSION_CODES.S)
    private fun startScan() {
        viewModel.clearDevice()
        if (bluetoothAdapter == null || !bluetoothAdapter!!.isEnabled) {
            //蓝牙开启失败
            Toast.makeText(this, "蓝牙未开启", Toast.LENGTH_SHORT).show()
            return
        }
        if (ActivityCompat.checkSelfPermission(
                this, Manifest.permission.BLUETOOTH_SCAN
            ) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
                this, Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            register(
                "scan", ActivityResultContracts.RequestMultiplePermissions()
            ) { map ->
                var isGrant = true
                map.values.forEach {
                    if (!it) {
                        isGrant = false
                    }
                }
                if (isGrant) {
                    if (bluetoothAdapter?.isDiscovering == true) {
                        bluetoothAdapter?.cancelDiscovery()
                    }
                    //蓝牙开启失败
                    Toast.makeText(this, "开始扫描", Toast.LENGTH_SHORT).show()
                    bluetoothAdapter?.startDiscovery()
                } else {
                    //蓝牙开启失败
                    Toast.makeText(this, "扫描权限开启失败", Toast.LENGTH_SHORT).show()
                }
            }.launch(arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_FINE_LOCATION))
            return
        }
        if (bluetoothAdapter?.isDiscovering == true) {
            bluetoothAdapter?.cancelDiscovery()
        }
        //蓝牙开启失败
        Toast.makeText(this, "开始扫描", Toast.LENGTH_SHORT).show()
        bluetoothAdapter?.startDiscovery()

    }

    val scanCallback = object : ScanCallback() {
        @SuppressLint("MissingPermission")
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            super.onScanResult(callbackType, result)
            Log.d("onScanResult", "callbackType: $callbackType result: $result")
            GlobalScope.launch {
                val device: BluetoothDevice = result.device
                val rssi = result.rssi
                val scanRecord = result.scanRecord
                val name = device.name
                val address = device.address
                val type = device.type
                val uuids = device.uuids
                val serviceData = scanRecord?.serviceData
                val manufacturerSpecificData = scanRecord?.manufacturerSpecificData
                val serviceUuids = scanRecord?.serviceUuids
                val bytes = scanRecord?.bytes
                val advertiseFlags = scanRecord?.advertiseFlags
                val txPowerLevel = scanRecord?.txPowerLevel
                val deviceName = scanRecord?.deviceName
                val timestampNanos = result.timestampNanos
                Log.d(
                    "onScanResult",
                    "device: $device, rssi: $rssi, name: $name, address: $address, type: $type, uuids: $uuids, serviceData: $serviceData, manufacturerSpecificData: $manufacturerSpecificData, serviceUuids: $serviceUuids, bytes: $bytes, advertiseFlags: $advertiseFlags, txPowerLevel: $txPowerLevel, deviceName: $deviceName, timestampNanos: $timestampNanos"
                )
                val uuid = if (!serviceUuids.isNullOrEmpty()) serviceUuids[0].toString() else ""
                if (name != null && address != null) {
                    onDeviceFound(
                        DeviceInfoBean(
                            name,
                            address,
                            isBonded = false,
                            isConnected = false,
                            serviceUUID = uuid
                        )
                    )
                }
            }
        }

        override fun onScanFailed(errorCode: Int) {
            super.onScanFailed(errorCode)
            Log.d("onScanFailed", "errorCode: $errorCode")
        }

    }

    private fun startScan2() {

        if (checkPermission(Manifest.permission.BLUETOOTH_CONNECT) || checkPermission(Manifest.permission.BLUETOOTH_SCAN)) {
            Toast.makeText(this, "权限缺失", Toast.LENGTH_SHORT).show()
            return
        }
        bluetoothScanner = bluetoothAdapter?.bluetoothLeScanner
        if (bluetoothScanner == null) {
            //蓝牙开启失败
            Toast.makeText(this, "蓝牙开启失败", Toast.LENGTH_SHORT).show()
            return
        }
        val scanSettings = ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build()
        val scanFilters = mutableListOf<ScanFilter>()
        val scanFilter = ScanFilter.Builder()
//            .setDeviceName("tangdekun")
            .setServiceUuid(ParcelUuid(mGATTServiceUUID))
            .build()


        val scanFilter1 = ScanFilter.Builder()
            .setDeviceName("tangdekun")
            .build()
        scanFilters.add(scanFilter)
        scanFilters.add(scanFilter1)

        Log.d("onScanResult", "startScan")
        if (isScanning) {
            bluetoothScanner?.stopScan(scanCallback)
        }
        isScanning = true
        bluetoothScanner?.startScan(scanFilters, scanSettings, scanCallback)
//        bluetoothScanner?.startScan(scanCallback)
    }

    @SuppressLint("MissingPermission")
    fun stopScan() {
        if (isScanning) {
            bluetoothScanner?.stopScan(scanCallback)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        advertiser = null
        mAdvertiseCallback = null
        unregisterBlueToothReceiver()
    }


    private fun registerBlueToothReceiver() {
        val filter = IntentFilter()
        filter.addAction(BluetoothDevice.ACTION_FOUND)
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED)
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
        filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)
        registerReceiver(receiver, filter)
    }

    private fun unregisterBlueToothReceiver() {
        unregisterReceiver(receiver)
    }

    //创建广播，监听蓝牙状态变化，包括开始扫描、结束扫描、扫描到结果、设备绑定状态改变、蓝牙开启状态改变等
    private val receiver = object : BroadcastReceiver() {
        @SuppressLint("MissingPermission")
        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
        override fun onReceive(context: Context?, intent: Intent?) {
            Log.d("Bluetooth", "onReceive")
            when (intent?.action) {
                BluetoothAdapter.ACTION_DISCOVERY_STARTED -> {
                    Log.d("Bluetooth", "开始扫描")
                }

                BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
                    Log.d("Bluetooth", "结束扫描")
                }

                BluetoothDevice.ACTION_FOUND -> {
                    val device: BluetoothDevice? =
                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice::class.java)
                    if (device != null) {
                        Log.d("Bluetooth", "扫描到设备：${device.name}")
                        val uuid = if (device.uuids.isNotEmpty()) device.uuids[0].uuid.toString() else ""
                        onDeviceFound(
                            DeviceInfoBean(
                                device.name,
                                device.address,
                                isBonded = false,
                                isConnected = false,
                                serviceUUID = uuid
                            )
                        )
                    }


                }

                BluetoothDevice.ACTION_BOND_STATE_CHANGED -> {
                    val device: BluetoothDevice? =
                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice::class.java)
                    when (device?.bondState) {
                        BluetoothDevice.BOND_BONDED -> {
                            Log.d("Bluetooth", "${device.name}配对成功")
                            var device = viewModel.blueToothDeviceList.find { it.address == device.address }
                            if (device != null) {
                                viewModel.updateDevice(
                                    DeviceInfoBean(
                                        device.name, device.address, isBonded = true, isConnected = false
                                    )
                                )
                            }

                        }

                        BluetoothDevice.BOND_BONDING -> {
                            Log.d("Bluetooth", "${device.name} ${device.address}配对中")
                        }

                        BluetoothDevice.BOND_NONE -> {
                            Log.d("Bluetooth", "${device.name} ${device.address}取消配对")
                        }
                    }
                }

                BluetoothDevice.ACTION_ACL_CONNECTED -> {
                    val device: BluetoothDevice? =
                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice::class.java)
                    Log.d("Bluetooth", "${device?.name}连接成功")
                }


            }
        }
    }

    private fun onDeviceFound(device: DeviceInfoBean?) {
        if (checkPermission(Manifest.permission.BLUETOOTH_CONNECT)) {
            return
        }
        Log.d("Bluetooth", "扫描到设备：${device.toString()}")
        if (device?.name != null) {
            viewModel.addDevice(device)
//            viewModel.blueToothDeviceList.removeIf { it.name == device.name }
        }
    }


    /**
     * 配对蓝牙设备
     */
    fun bondDevice(deviceInfoBean: DeviceInfoBean) {
        //在配对之前，停止搜索
        if (checkPermission(Manifest.permission.BLUETOOTH_CONNECT)) {
            bluetoothAdapter?.cancelDiscovery()
            return
        }
//        val device = bluetoothAdapter?.getRemoteDevice(deviceInfoBean.mac)
        val device =
            viewModel.blueToothDeviceList.find { it.address == deviceInfoBean.mac && it.name == deviceInfoBean.name }
        Log.d(TAG, "选择设备配对...${device?.name}....${device?.bondState}....${device?.address}")
        bluetoothAdapter?.cancelDiscovery()
        if (device?.bondState != BluetoothDevice.BOND_BONDED) { //没配对才配对
            try {
                Log.d(TAG, "开始配对...")
                val createBondMethod = BluetoothDevice::class.java.getMethod("createBond")
                val returnValue = createBondMethod.invoke(device) as Boolean
                if (returnValue) {
                    Log.d(TAG, "配对成功...")
                    Toast.makeText(this, "配对成功", Toast.LENGTH_SHORT).show()
                }
            } catch (e: NoSuchMethodException) {
                e.printStackTrace()
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
            } catch (e: InvocationTargetException) {
                e.printStackTrace()
            }
        } else {
            Log.d(TAG, "已经配对...")
            Toast.makeText(this, "已经配对", Toast.LENGTH_SHORT).show()
        }
    }

    //蓝牙连接
    fun connectDevice(deviceInfoBean: DeviceInfoBean): BluetoothSocket? {
//        val device: BluetoothDevice =
//            viewModel.blueToothDeviceList.find { it.address == deviceInfoBean.mac } ?: return null

        val device: BluetoothDevice? = bluetoothAdapter?.getRemoteDevice(deviceInfoBean.mac)
        if (device == null || checkPermission(Manifest.permission.BLUETOOTH_CONNECT)) {
            return null
        }
        Log.d(TAG, "选择设备配对...${device.name}....${device.bondState}....${device.address}")
        bluetoothAdapter?.cancelDiscovery()
        if (device.bondState != BluetoothDevice.BOND_BONDED) {
            Toast.makeText(this, "设备未配对", Toast.LENGTH_SHORT).show()
            return null
        }
        if (device.bondState == BluetoothDevice.BOND_BONDED) {
            Log.d(TAG, "开始连接...")
            var socket: BluetoothSocket? = null
            try {
                socket = device.createRfcommSocketToServiceRecord(mServiceUUID)
                if (socket != null && !socket.isConnected) {
                    socket.connect()
                }
            } catch (e: IOException) {
                socket?.close()
                e.printStackTrace()
                return null
            }
            return socket
        }
        return null
    }


    /**
     * 蓝牙是否连接
     * @return
     */
//    fun isConnectBlue(): Boolean {
//        return mBluetoothSocket != null && mBluetoothSocket.isConnected()
//    }

    //创建蓝牙服务端
    private fun createBluetoothServer() {
        if (mBluetoothServerSocket == null) {
            try {
                if (checkPermission(Manifest.permission.BLUETOOTH_CONNECT)) {
                    return
                }
                mBluetoothServerSocket = bluetoothAdapter?.listenUsingRfcommWithServiceRecord(
                    "BluetoothServer", mServiceUUID
                )
                GlobalScope.launch(Dispatchers.IO) {
                    var socket: BluetoothSocket? = null
                    while (true) {
                        try {
                            socket = mBluetoothServerSocket?.accept()
                            val outputStream = socket?.outputStream
                            outputStream?.write("连接成功".toByteArray())
                            outputStream?.flush()
                            while (true) {
                                val inputStream = socket?.inputStream
                                val buffer = ByteArray(1024)
                                val bytes = inputStream?.read(buffer)
                                if (bytes != null) {
                                    val msg = String(buffer, 0, bytes)
                                    Log.d("TAG", "接收到的消息：$msg")
                                }
                            }
                        } catch (e: IOException) {
                            e.printStackTrace()
                        }
                    }
                }
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

    val mGattServerCallback = object : BluetoothGattServerCallback() {

        override fun onConnectionStateChange(device: BluetoothDevice?, status: Int, newState: Int) {
            super.onConnectionStateChange(device, status, newState)
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                Log.d("TAG", "设备连接成功")
            }

            if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.d("TAG", "设备断开连接")
            }
        }


        @SuppressLint("MissingPermission")
        override fun onCharacteristicReadRequest(
            device: BluetoothDevice?,
            requestId: Int,
            offset: Int,
            characteristic: BluetoothGattCharacteristic?
        ) {
            super.onCharacteristicReadRequest(device, requestId, offset, characteristic)
            Log.d("TAG", "onCharacteristicReadRequest:${characteristic?.value.toString()} ")
            mBluetoothGattServer?.sendResponse(
                device,
                requestId,
                BluetoothGatt.GATT_SUCCESS,
                offset,
                characteristic?.value
            )
        }


        @SuppressLint("MissingPermission", "NewApi")
        override fun onCharacteristicWriteRequest(
            device: BluetoothDevice?,
            requestId: Int,
            characteristic: BluetoothGattCharacteristic?,
            preparedWrite: Boolean,
            responseNeeded: Boolean,
            offset: Int,
            value: ByteArray?
        ) {
            super.onCharacteristicWriteRequest(
                device,
                requestId,
                characteristic,
                preparedWrite,
                responseNeeded,
                offset,
                value
            )
            Log.d("TAG", "onCharacteristicWriteRequest :${String(value!!)}")
//            mBluetoothGattServer?.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value)
            // 向客户端发送消息
//            Log.d("TAG", "向客户端发送消息 : 你好 客户端，已经收到你的消息")
            Log.d("TAG", "device:$device : characteristic:${characteristic?.uuid.toString()}")
            if (device != null && characteristic != null) {

                Log.d("TAG", "向客户端发送消息 : 你好 客户端 已经收到你的消息")
                val value = "你好 客户端 已经收到你的消息".toByteArray()
                Log.d("TAG", "value size :${value.size}")
                mBluetoothGattServer?.notifyCharacteristicChanged(
                    device,
                    characteristic,
                    false,
                    value
                )
//                mBluetoothGattServer?.sendResponse(
//                    device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value
//                )
            }
        }

        override fun onMtuChanged(device: BluetoothDevice?, mtu: Int) {
            super.onMtuChanged(device, mtu)
            Log.d("TAG", "mtu :${mtu}")
        }

    }

    @SuppressLint("MissingPermission")
    fun createGattServer() {
        // 创建BluetoothGattServer
        mBluetoothGattServer = bluetoothManager?.openGattServer(this, mGattServerCallback)
        // 定义GATT服务和特征：
        val service = BluetoothGattService(mGATTServiceUUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)
        val characteristic = BluetoothGattCharacteristic(
            mGATTCharacteristicUUID,
            BluetoothGattCharacteristic.PROPERTY_READ or BluetoothGattCharacteristic.PROPERTY_WRITE or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
            BluetoothGattCharacteristic.PERMISSION_READ or BluetoothGattCharacteristic.PERMISSION_WRITE
        )
        val descriptor = BluetoothGattDescriptor(
            mGATTDescriptorUUID,
            BluetoothGattDescriptor.PERMISSION_READ or BluetoothGattDescriptor.PERMISSION_WRITE
        )


        // 添加描述符到特征
        characteristic.addDescriptor(descriptor)
        // 添加特征到服务
        service.addCharacteristic(characteristic)
        // 添加服务到GATT服务器
        mBluetoothGattServer?.addService(service)
//        // 保存BluetoothGattServer
//        this.mBluetoothGattServer = mBluetoothGattServer
//
//        // 开启广播
//        val mBluetoothLeAdvertiser = bluetoothAdapter?.bluetoothLeAdvertiser
//        val settings = AdvertiseSettings.Builder()
//            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
//            .setConnectable(true)
//            .setTimeout(0)
//            .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
//            .build()
//        val data = AdvertiseData.Builder()
//            .setIncludeDeviceName(true)
//            .setIncludeTxPowerLevel(true)
//            .addServiceUuid(ParcelUuid(mGATTServiceUUID))
//            .build()
//        mBluetoothLeAdvertiser?.startAdvertising(settings, data, mAdvertiseCallback)
    }

    private fun checkPermission(permission: String) = ActivityCompat.checkSelfPermission(
        this, permission
    ) != PackageManager.PERMISSION_GRANTED


    val gattCallback = object : BluetoothGattCallback() {
        @SuppressLint("MissingPermission")
        override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                Log.d("TAG", "连接成功")
                gatt?.discoverServices();
            }

            if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.d("TAG", "连接断开")
            }

            if (newState == BluetoothProfile.STATE_CONNECTING) {
                Log.d("TAG", "正在连接")
            }

            if (newState == BluetoothProfile.STATE_DISCONNECTING) {
                Log.d("TAG", "正在断开连接")
            }

            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d("TAG", "操作成功")
            }

            if (status == BluetoothGatt.GATT_FAILURE) {
                Log.d("TAG", "操作失败")
            }

            if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
                Log.d("TAG", "连接拥挤")
            }

            if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
                Log.d("TAG", "连接未授权")
            }

            if (status == BluetoothGatt.GATT_INSUFFICIENT_ENCRYPTION) {
                Log.d("TAG", "连接未加密")
            }

            if (status == BluetoothGatt.GATT_INVALID_OFFSET) {
                Log.d("TAG", "无效的偏移量")
            }
        }


        @SuppressLint("MissingPermission", "NewApi")
        override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
            super.onServicesDiscovered(gatt, status)
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d("TAG", "发现服务成功")
                val services = gatt?.services
                services?.forEach { bluetoothGattService ->
                    Log.d("TAG", "服务UUID: ${bluetoothGattService.uuid}")
                    if (bluetoothGattService.uuid.toString() == mGATTServiceUUID.toString()) {
                        val characteristics = bluetoothGattService.characteristics
                        characteristics?.forEach {
                            Log.d("TAG", "特征UUID: ${it.uuid}")
                            if (it.uuid.toString() == mGATTCharacteristicUUID.toString()) {
                                val properties = it.properties
                                if (properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
                                    Log.d("TAG", "支持读和通知")
                                    gatt.setCharacteristicNotification(it, true)
                                    val descriptor = it.getDescriptor(mGATTDescriptorUUID)
                                    if (descriptor != null) {
                                        gatt.writeDescriptor(
                                            descriptor,
                                            BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                                        )
                                    }

//                                在注册消息监听，都是使用UUID值是00002902-0000-1000-8000-00805f9b34fb进行的。这个是Android系统保留的。用于动态监听的。

//                                    var descriptor = BluetoothGattDescriptor(   //这个是用于设置通知的
//                                        UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"),
//                                        BluetoothGattDescriptor.PERMISSION_WRITE
//                                    )
//                                    it.addDescriptor(descriptor)
////                                    val descriptor =
////                                        it.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))
//                                    if (descriptor != null) {
//                                        gatt.setCharacteristicNotification(it, true)
//                                        gatt.writeDescriptor(
//                                            descriptor,
//                                            BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
//                                        )
//                                    }
                                }


                                GlobalScope.launch {
                                    //获取mtu
                                    if (gatt.requestMtu(512)) {
                                        Log.d("TAG", "requestMtu success")
                                    } else {
                                        Log.d("TAG", "requestMtu failed")
                                    }
                                    delay(2000)
                                    //发送“你好，服务端”
                                    val value = "你好，服务端".toByteArray()
//                                it.setValue(value)
                                    gatt.writeCharacteristic(it, value, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)

                                }



                            }
//
                        }
                    }
                }
            }
        }

        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray
        ) {
            super.onCharacteristicChanged(gatt, characteristic, value)

            Log.d("TAG", "特征值改变")
            Log.d("TAG", "特征值大小: ${value.size}__${String(value, charset("UTF-8"))}")

        }

        override fun onCharacteristicRead(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray,
            status: Int
        ) {
            super.onCharacteristicRead(gatt, characteristic, value, status)
            Log.d("TAG", "特征值读取: $value)}")
            Log.d("TAG", "特征值: ${String(value)}")

        }

        @SuppressLint("MissingPermission")
        override fun onCharacteristicWrite(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic?,
            status: Int
        ) {
            super.onCharacteristicWrite(gatt, characteristic, status)
            Log.d("TAG", "特征值写入")

            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d("TAG", "特征值写入成功 characteristic:$characteristic")
            }
        }


        override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
            super.onMtuChanged(gatt, mtu, status)
            Log.d("TAG", "client mtu:$mtu")
        }
    }

    fun connectGattService(deviceInfoBean: DeviceInfoBean): BluetoothGatt? {
        val device: BluetoothDevice? = bluetoothAdapter?.getRemoteDevice(deviceInfoBean.mac)
        if (device == null || checkPermission(Manifest.permission.BLUETOOTH_CONNECT)) {
            Toast.makeText(this, "设备不存在", Toast.LENGTH_SHORT).show()
            return null
        }
        stopScan()
        return device.connectGatt(this, false, gattCallback)
    }

    @SuppressLint("MissingPermission")
    fun discoverServices(gatt: BluetoothGatt?) {
        if (gatt == null) {
            return
        }
        gatt.discoverServices()
        gatt.disconnect()
    }


}
